﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using AMM.Model;
using AMM.Model.Produce;

namespace AMM.DataAccess.Produce {
    public class ProducePlanRepository : BaseRepository<ProducePlan> {

        private int _pageSize;

        public ProducePlanRepository(int pageSize) {
            this._pageSize = pageSize;
        }

        public ProducePlan FetchProducePlanById(int producePlanId) {
            using (var ctx = this.Context) {
                return ctx.ProducePlans.Find(producePlanId);
            }
        }

        public List<ProducePlan> FetchProducePlanByProduceConductId(int produceConductId) {
            using (var ctx = this.Context) {
                return ctx.ProducePlans
                    .Where(x => x.ProduceConductId == produceConductId)
                    .ToList();
            }
        }

        public List<ProducePlan> FetchProducePlanForViewByProduceConductId(int produceConductId) {
            using (var ctx = this.Context) {
                return ctx.ProducePlans
                    .Include("Basic")
                    .Where(x => x.ProduceConductId == produceConductId)
                    .ToList();
            }
        }

        public List<ProducePlan> FetchProducePlanForView() {
            using (var ctx = this.Context) {
                return ctx.ProducePlans
                    .Include("Basic")
                    .Include("ProduceConduct")
                    .ToList();
            }
        }

        public void UpdateProducePlan(List<ProducePlan> producePlanList) {
            using (var ctx = this.Context) {
                using (DbContextTransaction trans = ctx.Database.BeginTransaction()) {
                    try {
                        producePlanList.ForEach(x => {
                            switch (x.ClassStatus) {
                                case ClassStatus.UnChanged:
                                    ctx.ProducePlans.Attach(x);
                                    ctx.Entry(x).State = EntityState.Unchanged;
                                    break;
                                case ClassStatus.Updated:
                                    x.ModifiedDatetime = DateTime.Now;
                                    ctx.ProducePlans.Attach(x);
                                    ctx.Entry(x).State = EntityState.Modified;
                                    break;
                                case ClassStatus.Added:
                                    x.CreatedDatetime = DateTime.Now;
                                    ctx.ProducePlans.Attach(x);
                                    ctx.Entry(x).State = EntityState.Added;
                                    break;
                                case ClassStatus.Deleted:
                                    ctx.ProducePlans.Attach(x);
                                    ctx.Entry(x).State = EntityState.Deleted;
                                    break;
                            }
                        });

                        ctx.SaveChanges();
                        trans.Commit();
                    }
                    catch (Exception ex) {
                        trans.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public void DeleteMultipleProducePlan(params int[] producePlanIds) {
            using (var ctx = this.Context) {
                using (DbContextTransaction trans = ctx.Database.BeginTransaction()) {
                    try {
                        ctx.ProducePlans.Where(x => producePlanIds.Contains(x.ProducePlanId)).ToList().ForEach(x => {
                            ctx.ProducePlans.Remove(x);
                        });
                        ctx.ProducePlans.Where(x => producePlanIds.Contains(x.ProducePlanId)).ToList().ForEach(x => {
                            ctx.ProducePlans.Remove(x);
                        });
                        ctx.SaveChanges();
                        trans.Commit();
                    }
                    catch (Exception ex) {
                        trans.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public List<ProduceConduct> FetchProduceConductForPlanList(ProducePlanSearchModel searchModel, int pageIndex) {
            using (var ctx = this.Context) {
                var query = ctx.ProduceConducts
                    .Include("Basic")
                    .Include("CustomerOrder")
                    .Include("Product")
                    .Include("ProcurementOrder")
                    .Include("ProducePlans")
                    .Where(x => x.ProduceConductId != 0);

                if (!string.IsNullOrEmpty(searchModel.ProduceProductCode)) {
                    query = query.Where(x => x.Code.Contains(searchModel.ProduceProductCode));
                }
                if (!string.IsNullOrEmpty(searchModel.ProductCode)) {
                    query = query.Where(x => x.Product.Code.Contains(searchModel.ProductCode));
                }
                if (searchModel.PlanDateStart.HasValue) {
                    query = query.Where(x => x.ProducePlans.Any(y => y.PlanDate >= DbFunctions.TruncateTime(searchModel.PlanDateStart.Value)));
                }
                if (searchModel.PlanDateEnd.HasValue) {
                    query = query.Where(x => x.ProducePlans.Any(y => y.PlanDate <= DbFunctions.TruncateTime(searchModel.PlanDateEnd.Value)));
                }
                if (searchModel.ProduceUnitId.HasValue) {
                    query = query.Where(x => x.ProducePlans.Any(y => y.ProduceUnitId == searchModel.ProduceUnitId.Value));
                }

                searchModel.Records = query.Count();
                pageIndex = (pageIndex - 1) * this._pageSize > searchModel.Records ? 1 : pageIndex;

                return query.OrderByDescending(x => x.CreatedDatetime).Skip((pageIndex - 1) * this._pageSize).Take(this._pageSize).ToList();
            }
        }

    }
}
